﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Xml;
using System.Xml.Linq;
using System.Threading;
using System.Web;

namespace LastFmClient
{
    public class Artist : Client
    {
        private string m_TagUrl = "http://ws.audioscrobbler.com/1.0/artist/*ARTIST*/toptags.xml";
        private string m_SimilarArtistsUrl = "http://ws.audioscrobbler.com/1.0/artist/*ARTIST*NAME*/similar.xml";

        private string m_MostKnownTracksUrl = "http://ws.audioscrobbler.com/1.0/artist/*ARTIST*NAME*/toptracks.xml";

        public Artist(string ArtistName)
        {
            if (string.IsNullOrEmpty(ArtistName))
                throw new Exception("Artist name is null or empty.");

            m_TagUrl = m_TagUrl.Replace("*ARTIST*", HttpUtility.UrlEncode(ArtistName));
            //m_TagUrl = HttpUtility.UrlEncode(m_TagUrl);

            m_SimilarArtistsUrl = m_SimilarArtistsUrl.Replace("*ARTIST*NAME*", HttpUtility.UrlEncode(ArtistName));
            //m_SimilarArtistsUrl = HttpUtility.UrlEncode(m_SimilarArtistsUrl);

            m_MostKnownTracksUrl = m_MostKnownTracksUrl.Replace("*ARTIST*NAME*", HttpUtility.UrlEncode(ArtistName));

            m_ArtistName = ArtistName;
        }

        private string m_ArtistName;
        public string Name
        {
            get
            {
                return m_ArtistName;
            }
        }

        // similar artists

        private XElement m_SimilarArtistsRoot;
        private XElement SimilarArtistsRoot
        {
            get
            {
                if (m_SimilarArtistsRoot == null)
                {
                    m_SimilarArtistsRoot = GetXElement(m_SimilarArtistsUrl);             
                }
                return m_SimilarArtistsRoot;
            }
        }

        public IEnumerable<SimilarAtist> SimilarArtists
        {
            get
            {
                IEnumerable<SimilarAtist> simArtists =
                    from el in SimilarArtistsRoot.Elements("artist")
                    select new SimilarAtist(el);

                return simArtists;
            }
        }

        public SimilarAtist TopSimilarArtist
        {
            get
            {
                return SimilarArtists.OrderByDescending(p => p.Match).First();
            }
        }

        // tags

        private XElement m_TagsRoot;
        private XElement TagsRoot
        {
            get
            {
                if (m_TagsRoot == null)
                {
                    m_TagsRoot = GetXElement(m_TagUrl);                   
                }

                return m_TagsRoot;
            }
        }

        public IEnumerable<Tag> Tags
        {
            get
            {
                IEnumerable<Tag> tags =
                    from el in TagsRoot.Elements("tag")
                    select new Tag(el);

                return tags;
            }
        }

        public Tag TopTag
        {
            get
            {
                return Tags.OrderByDescending(p => p.Count).First();
            }
        }

        public IEnumerable<Tag> Top5Tags
        {
            get
            {
                return GetTopNTags(5);
            }
        }

        public IEnumerable<Tag> GetTopNTags(int n)
        {
            return Tags.OrderByDescending(p => p.Count).Take(n);
        }


        //most known tracks


        private XElement m_MostKnownTracksRoot;
        private XElement MostKnownTracksRoot
        {
            get
            {
                if (m_MostKnownTracksRoot == null)
                {
                    m_MostKnownTracksRoot = GetXElement(m_MostKnownTracksUrl);
                }

                return m_MostKnownTracksRoot;
            }
        }

        public IEnumerable<Track> MostKnownTracks
        {
            get
            {
                IEnumerable<Track> MostKnownTracks =
                    from el in MostKnownTracksRoot.Elements("track")
                    select new Track(el.Element("name").Value, this.Name);

                return MostKnownTracks;
            }
        }
    }
}
